home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 6 / develop 6 code / TCP / NewsWatcher / NewsWatcher 2.0d15 source / source / tcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-27  |  8.0 KB  |  342 lines  |  [TEXT/KAHL]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     tcp.c
  4.  
  5.     This module handle all the high-level calls to MacTCP.
  6.     
  7.     Portions copyright © 1990, Apple Computer.
  8.     Portions copyright © 1993, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #include "MacTCPCommonTypes.h"
  16. #include "TCPPB.h"
  17.  
  18. #include "glob.h"
  19. #include "tcp.h"
  20. #include "tcplow.h"
  21. #include "util.h"
  22.  
  23.  
  24. #ifndef MAX_WDS
  25. #define MAX_WDS        6
  26. #endif
  27.  
  28.  
  29. /* InitNetwork opens the network driver. */
  30.  
  31. OSErr InitNetwork (void)
  32. {
  33.     return OpenTCPDriver();
  34. }
  35.  
  36.  
  37. /* CreateStream() creates an unconnected network stream to be
  38.    used later by OpenConnection.  The length of the receive
  39.    buffer must be specified in the call. */
  40.    
  41. OSErr CreateStream (unsigned long *stream, unsigned long recvLen)
  42. {
  43.     Ptr recvPtr;
  44.     OSErr err;
  45.     
  46.     recvPtr = MyNewPtr(recvLen);
  47.     if ((err = MyMemErr())==noErr)
  48.         err = LowTCPCreateStream(stream,recvPtr,recvLen,(TCPNotifyProc)nil);
  49.     return err;
  50. }
  51.     
  52.  
  53. /* ReleaseStream() frees the allocated buffer space for a given connection
  54.    stream.  This call should be made after CloseConnection. */
  55.    
  56. OSErr ReleaseStream (unsigned long stream)
  57. {
  58.     OSErr err;
  59.     Ptr recvPtr;
  60.     unsigned long recvLen;
  61.     
  62.     if ((err = LowTCPRelease(stream,&recvPtr,&recvLen)) == noErr)
  63.         MyDisposPtr(recvPtr);
  64.     return err;
  65. }
  66.  
  67.  
  68. /* OpenConnection() initiates a connection to a remote machine,
  69.    given that machine's network number and connection port.  A timeout
  70.    value for the call must be given, and the stream identifier is returned. */
  71.  
  72. OSErr OpenConnection (unsigned long stream, long remoteHost, short remotePort,
  73.     Byte timeout)
  74. {
  75.     ip_addr localHost;
  76.     tcp_port localPort = 0;
  77.     
  78.     return LowTCPOpenConnection(stream,timeout,remoteHost,remotePort,&localHost,
  79.                                 &localPort);
  80. }
  81.  
  82.  
  83. /* WaitForConnection() listens for a connection on a particular port from a
  84.     particular host.  It returns when a connection has been established. */
  85.  
  86. OSErr WaitForConnection (unsigned long stream, Byte timeout, short localPort,
  87.                         long *remoteHost, short *remotePort)
  88. {
  89.     ip_addr localHost;
  90.     
  91.     return LowTCPWaitForConnection(stream,timeout,(ip_addr *)remoteHost,
  92.                 (tcp_port *)remotePort,&localHost,(tcp_port *)&localPort,false,nil);
  93. }
  94.  
  95.  
  96. /*    AsyncWaitForConnection() listens for a connection on a particular port from a
  97.     particular host.  It is executed asynchronously and returns immediately */
  98.  
  99. OSErr AsyncWaitForConnection (unsigned long stream, Byte timeout,
  100.     short localPort, long remoteHost, short remotePort, TCPiopb **returnBlock)
  101. {
  102.     ip_addr localHost;
  103.     
  104.     return LowTCPWaitForConnection(stream,timeout,(ip_addr *)&remoteHost,
  105.                 (tcp_port *)&remotePort,&localHost,(tcp_port *)&localPort,true,returnBlock);
  106. }
  107.  
  108.  
  109. /*    AsyncGetConnectionData() should be called when a call to AsyncWaitForConnection
  110.     completes (when returnBlock->ioResult <= 0).  This call retrieves the information
  111.     about this new connection and disposes the parameter block. */
  112.     
  113. OSErr AsyncGetConnectionData (TCPiopb *returnBlock, long *remoteHost,
  114.     short *remotePort)
  115. {
  116.     ip_addr localHost;
  117.     tcp_port localPort;
  118.     
  119.     return LowFinishTCPWaitForConn(returnBlock,(ip_addr *)remoteHost,
  120.                         (tcp_port *)remotePort,&localHost,&localPort);
  121. }
  122.  
  123.  
  124. /*     IsAUX is a helper function used by CloseConnection to figure out whether 
  125.     we are running under A/UX. */
  126.     
  127. static Boolean IsAUX (void)
  128. {
  129.     return ((*(short*)0xB22) & (1<<9)) != 0;
  130. }
  131.  
  132.  
  133. /* CloseConnection() terminates a connection to a remote host, given the
  134.    stream identifier of the connection. It waits for the remote host to also
  135.    close its end of the connection. */
  136.    
  137. OSErr CloseConnection (unsigned long stream, Boolean waitForOtherSideToCloseFirst)
  138. {
  139.     unsigned short length;
  140.     CStr255 data;
  141.     OSErr err;
  142.     
  143.     if (IsAUX()) {
  144.         err = LowTCPClose(stream, 10);
  145.         if (err != noErr) goto exit;
  146.         return noErr;
  147.     }
  148.     
  149.     if (!waitForOtherSideToCloseFirst) {
  150.         err = LowTCPClose(stream, 10);
  151.         if (err != noErr && err != connectionDoesntExist &&
  152.             err != connectionClosing && err != connectionTerminated) goto exit;
  153.     }
  154.  
  155.     while (true) {
  156.         length = 256;
  157.         err = RecvData(stream, data, &length, true);
  158.         if (err != noErr) break;
  159.     }
  160.     
  161.     if (waitForOtherSideToCloseFirst) {
  162.         err = LowTCPClose(stream, 10);
  163.         if (err != noErr) goto exit;
  164.     }
  165.     
  166.     return noErr;
  167.  
  168. exit:
  169.  
  170.     AbortConnection(stream);
  171.     return err;
  172. }
  173.  
  174.  
  175. /* AbortConnection() aborts a connection to a remote host, given the
  176.    stream identifier of the connection */
  177.    
  178. OSErr AbortConnection (unsigned long stream)
  179. {
  180.     return LowTCPAbort(stream);
  181. }
  182.  
  183.  
  184. /* SendData() sends data along a connection stream to a remote host. */
  185.  
  186. OSErr SendData (unsigned long stream, Ptr data, unsigned short length)
  187. {    
  188.     struct wdsEntry myWDS[2];    /* global write data structure */
  189.  
  190.     myWDS[0].length = length;
  191.     myWDS[0].ptr = data;
  192.     myWDS[1].length = 0;
  193.     myWDS[1].ptr = nil;
  194.     return LowTCPSendData(stream,120,false,false,(Ptr) myWDS,false,nil);
  195. }
  196.  
  197. /* SendMultiData() is similar to SendData, but takes an array of strings to send
  198.    to the remote host. 
  199.  
  200.     A/UX versions previous to and including 3.0b15 have a fixed limit of
  201.     6 WDS segments per TCPSend.
  202.     So we enforce that limit since folks using SendMultiData may want
  203.     to send more than 6 chucks of data.
  204. */
  205.  
  206. OSErr SendMultiData (unsigned long stream, CStr255 data[], short numData)
  207. {
  208.     struct wdsEntry theWDS[MAX_WDS+1];
  209.     short i = 0, j, numToSend;
  210.     OSErr err = noErr;
  211.  
  212.     while (numData > 0 && err == noErr) {
  213.         numToSend = (numData > MAX_WDS) ? MAX_WDS : numData;
  214.         for (j=0; j < numToSend; i++,j++) {
  215.             theWDS[j].ptr = (Ptr)data[i];
  216.             theWDS[j].length = strlen((Ptr)data[i]);
  217.         }
  218.         theWDS[numToSend].ptr = nil;
  219.         theWDS[numToSend].length = 0;
  220.         err = LowTCPSendData(stream,120,false,false,(Ptr)theWDS,false,nil);
  221.         numData -= numToSend;
  222.     }
  223.  
  224.     return err;
  225. }
  226.  
  227.  
  228. /* RecvData() waits for data to be received on a connection stream.  When data
  229.    arrives, it is copied into the data buffer and the call terminates. */
  230.  
  231. OSErr RecvData (unsigned long stream, Ptr data, unsigned short *length,
  232.     Boolean retry)
  233. {
  234.     Boolean    urgent,mark;
  235.     OSErr    err;
  236.     unsigned short recvLength;
  237.  
  238.     do {
  239.         recvLength = *length-1;
  240.         err = LowTCPRecvData(stream,40,&urgent,&mark,data,&recvLength,false,nil);
  241.     }
  242.     while (retry && err==commandTimeout);
  243.     *length = recvLength;
  244.     if (err == noErr) *(data+*length) = 0;
  245.     return err;
  246. }
  247.  
  248.  
  249. /*    GetConnectionState gets the connection state of a stream. */
  250.  
  251. OSErr GetConnectionState (unsigned long stream, byte *state)
  252. {
  253.     TCPStatusPB theStatus;
  254.     OSErr err;
  255.     
  256.     err = LowTCPStatus(stream,&theStatus);
  257.     if (err == connectionDoesntExist) {
  258.         *state = 0;
  259.         return noErr;
  260.     }
  261.     *state = theStatus.connectionState;
  262.     return err;
  263. }
  264.  
  265.  
  266. /*    IPNameToAddr invokes the domain name system to translate a domain name
  267.     into an IP address. */
  268.     
  269. OSErr IPNameToAddr (char *name, unsigned long *addr)
  270. {
  271.     OSErr err;
  272.     short i;
  273.     static struct {
  274.         CStr255 name;
  275.         unsigned long addr;
  276.     } cache[10];
  277.     static short numCache=0;
  278.     
  279.     for (i=0; i<numCache; i++) {
  280.         if (strcmp(name, cache[i].name) == 0) {
  281.             *addr = cache[i].addr;
  282.             return noErr;
  283.         }
  284.     }
  285.     if ((err = LowIPNameToAddr(name, addr)) != noErr) return err;
  286.     if (numCache < 10) {
  287.         strcpy(cache[numCache].name, name);
  288.         cache[numCache].addr = *addr;
  289.         numCache++;
  290.     }
  291.     return noErr;
  292. }
  293.  
  294.  
  295. /*    IPAddrToName invokes the domain name system to translate an IP address
  296.     into a domain name. */
  297.     
  298. OSErr IPAddrToName (unsigned long addr, char *name)
  299. {
  300.     return LowIPAddrToName(addr, name);
  301. }
  302.  
  303.  
  304. /*    GetMyIPAddr returns the IP address of this Mac. */
  305.  
  306. OSErr GetMyIPAddr (unsigned long *addr)
  307. {
  308.     return LowGetMyIPAddr(addr);
  309. }
  310.  
  311.  
  312. /*    GetMyIPAddrStr returns the IP address of this Mac as a dotted decimal
  313.     string. */
  314.     
  315. OSErr GetMyIPAddrStr (char *addrStr)
  316. {
  317.     return LowGetMyIPAddrStr(addrStr);
  318. }
  319.  
  320.  
  321. /*    GetMyIPName returns the domain name of this Mac. */
  322.  
  323. OSErr GetMyIPName (char *name)
  324. {
  325.     unsigned long addr;
  326.     short len;
  327.     static OSErr err;
  328.     static Boolean gotIt=false;
  329.     static CStr255 theName;
  330.     
  331.     if (!gotIt) {
  332.         if ((err = LowGetMyIPAddr(&addr)) != noErr) return err;
  333.         err = LowIPAddrToName(addr,theName);
  334.         gotIt = true;
  335.         len = strlen(theName);
  336.         if (theName[len-1] == '.') theName[len-1] = 0;
  337.     }
  338.     if (err != noErr) return err;
  339.     strcpy(name,theName);
  340.     return noErr;
  341. }
  342.